﻿using System;
using System.Diagnostics;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.Transactions;

namespace RockBus.ServiceModel
{
    public static class RoutingUtilities
    {
        //static RoutingUtilities()
        //{
        //    Type soapProcessingInspectorType = Type.GetType(
        //        "System.ServiceModel.Routing.SoapProcessingBehavior+SoapProcessingInspector, System.ServiceModel.Routing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35");
        //    MethodInfo MarshalMessageMethodInfo = soapProcessingInspectorType.GetMethod(
        //        "MarshalMessage", BindingFlags.Instance | BindingFlags.NonPublic
        //}

        // Fields
        public const string RoutingNamespace = "http://schemas.microsoft.com/netfx/2009/05/routing";

        // Methods
        public static void Abort(ICommunicationObject commObj, object identifier)
        {
            commObj.Abort();
        }

        public static string GetAddressingNamespace(AddressingVersion addressing)
        {
            if (addressing == AddressingVersion.WSAddressingAugust2004)
            {
                return "http://schemas.xmlsoap.org/ws/2004/08/addressing";
            }
            if (addressing == AddressingVersion.WSAddressing10)
            {
                return "http://www.w3.org/2005/08/addressing";
            }
            if (addressing != AddressingVersion.None)
            {
                throw new ArgumentException("addressing");
            }
            return "http://schemas.microsoft.com/ws/2005/05/addressing/none";
        }

        public static bool IsMessageUsingWSSecurity(UnderstoodHeaders understoodHeaders)
        {
            foreach (MessageHeaderInfo info in understoodHeaders)
            {
                if ((string.Equals(info.Namespace, "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd", StringComparison.Ordinal) || string.Equals(info.Namespace, "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd", StringComparison.Ordinal)) || string.Equals(info.Namespace, "http://docs.oasis-open.org/wss/oasis-wss-wsecurity-secext-1.1.xsd", StringComparison.Ordinal))
                {
                    return true;
                }
            }
            return false;
        }

        public static bool IsRoutingServiceNamespace(string contractNamespace)
        {
            return string.Equals(contractNamespace, "http://schemas.microsoft.com/netfx/2009/05/routing", StringComparison.Ordinal);
        }

        public static bool IsTransactedReceive(Binding binding, BindingParameterCollection bindingParameters)
        {
            ITransactedBindingElement property = binding.GetProperty<ITransactedBindingElement>(bindingParameters);
            if (property != null)
            {
                return property.TransactedReceiveEnabled;
            }
            foreach (BindingElement element2 in binding.CreateBindingElements())
            {
                property = element2 as ITransactedBindingElement;
                if ((property != null) && property.TransactedReceiveEnabled)
                {
                    return true;
                }
            }
            return false;
        }

        [Conditional("DEBUG")]
        public static void TraceTransactionInfo(string tag, Transaction transaction = null)
        {
            if (null == transaction)
            {
                transaction = Transaction.Current;
            }

            if (null != transaction)
            {
                Debug.WriteLine("[{0}] {1} - TransactionInformation: {2}, {3}, {4}, {5}",
                    DateTime.Now,
                    tag,
                    Transaction.Current.TransactionInformation.CreationTime,
                    Transaction.Current.TransactionInformation.LocalIdentifier,
                    Transaction.Current.TransactionInformation.DistributedIdentifier,
                    Transaction.Current.TransactionInformation.Status);
            }
            else
            {
                Debug.WriteLine("[{0}] {1} - TransactionInformation: None (no ambient transaction).",
                    DateTime.Now,
                    tag);
            }
        }

        public static Transaction TryGetTransaction(Message message)
        {
            if (!message.Properties.ContainsKey("TransactionMessageProperty"))
            {
                return null;
            }
            return ((TransactionMessageProperty)message.Properties["TransactionMessageProperty"]).Transaction;
        }
    }
}